home *** CD-ROM | disk | FTP | other *** search
/ Turnbull China Bikeride / Turnbull China Bikeride - Disc 2.iso / STUTTGART / UNIXTOOL / M4SRC / _files / _M4 / Misc._C < prev    next >
Encoding:
Text File  |  1989-10-15  |  5.5 KB  |  318 lines

  1. /*
  2.  * misc.c
  3.  * Facility: m4 macro processor
  4.  * by: oz
  5.  */
  6.  
  7. #include "mdef.h"
  8. #include "extr.h" 
  9.  
  10. #include <signal.h> 
  11. #include <string.h>
  12. #include <stdlib.h>
  13. #include <stdarg.h>
  14.  
  15. static void killdiv (void);
  16.  
  17. /*
  18.  * indx - find the index of second str in the
  19.  *        first str.
  20.  */
  21. int indx (char *s1, char *s2)
  22. {
  23.         register char *t;
  24.         register char *p;
  25.         register char *m;
  26.  
  27.         for (p = s1; *p; p++) {
  28.                 for (t = p, m = s2; *m && *m == *t; m++, t++)
  29.                         ;
  30.                 if (!*m)
  31.                         return(p - s1);
  32.         }
  33.         return (-1);
  34. }
  35.  
  36. /*
  37.  *  putback - push character back onto input
  38.  *
  39.  */
  40. void putback (char c)
  41. {
  42.         if (bp < endpbb)
  43.                 *bp++ = c;
  44.         else
  45.                 error("M4: Too many characters pushed back");
  46. }
  47.  
  48. /*
  49.  *  pbstr - push string back onto input
  50.  *          putback is replicated to improve
  51.  *          performance.
  52.  *
  53.  */
  54. void pbstr (char *s)
  55. {
  56.         register char *es;
  57.     register char *zp;
  58.  
  59.     es = s;
  60.     zp = bp;
  61.  
  62.         while (*es)
  63.                 es++;
  64.         es--;
  65.         while (es >= s)
  66.                 if (zp < endpbb)
  67.                         *zp++ = *es--;
  68.         if ((bp = zp) == endpbb)
  69.                 error("M4: Too many characters pushed back");
  70. }
  71.  
  72. /*
  73.  *  pbnum - convert number to string, push back on input.
  74.  *
  75.  */
  76. void pbnum (int n)
  77. {
  78.         register int num;
  79.  
  80.         num = (n < 0) ? -n : n;
  81.         do {
  82.                 putback(num % 10 + '0');
  83.         }
  84.         while ((num /= 10) > 0);
  85.  
  86.         if (n < 0) putback('-');
  87. }
  88.  
  89. /*
  90.  *  putchr - output a single character (or put it on the string space)
  91.  *
  92.  */
  93. void putchr (char c)
  94. {
  95.     if (sp < 0)
  96.     {
  97.         if (active != NULL)
  98.                     putc(c, active);
  99.     }
  100.         else if (ep < endest)
  101.                 *ep++ = c;
  102.         else
  103.                 error("M4: String space overflow");
  104. }
  105.  
  106. /*
  107.  *  putstr - output a string (or put it on the string space)
  108.  *
  109.  */
  110. void putstr (char *s)
  111. {
  112.     if (sp < 0)
  113.     {
  114.         if (active != NULL)
  115.                     fputs(s, active);
  116.     }
  117.         else if (endest - ep < strlen(s))
  118.                 error("M4: String space overflow");
  119.         else
  120.         {
  121.             while (*s)
  122.                     *ep++ = *s++;
  123.     }
  124. }
  125.  
  126. /*
  127.  * getdiv - read in a diversion file, and trash it.
  128.  * Caller must check that the diversion is in use.
  129.  */
  130. void getdiv (int ind)
  131. {
  132.         register int c;
  133.         register FILE *dfil;
  134.  
  135.         if (outfile[ind].fp != NULL)
  136.                 error("M4: Undivert: diversion %d still active", ind);
  137.  
  138.         if ((dfil = fopen(outfile[ind].name, "r")) == NULL)
  139.                 error("M4: Cannot undivert diversion %d", ind);
  140.  
  141.     if (active != NULL)
  142.     {
  143.             while((c = getc(dfil)) != EOF)
  144.                     putc(c, active);
  145.         }
  146.  
  147.         (void) fclose(dfil);
  148.  
  149.         if (remove(outfile[ind].name))
  150.                 error("M4: Cannot delete %s", outfile[ind].name);
  151.  
  152.     outfile[ind].ptr = 0L;
  153. }
  154.  
  155. /*
  156.  * Very fatal error. Close all files
  157.  * and die hard.
  158.  */
  159. void error (char *fmt, ...)
  160. {
  161.     va_list ap;
  162.         killdiv ();
  163.     va_start (ap, fmt);
  164.         vfprintf (stderr, fmt, ap);
  165.         va_end (ap);
  166.         putc ('\n', stderr);
  167.         exit (1);
  168. }
  169.  
  170. /*
  171.  * Interrupt handling
  172.  */
  173. void onintr (int sig)
  174. {
  175.     if ( sig == SIGINT )
  176.             error ("\nEscape pressed.");
  177.     else
  178.         error ("\nUnexpected signal.");
  179. }
  180.  
  181. /*
  182.  * save a string somewhere..
  183.  *
  184.  */
  185. char *strsave (char *s)
  186. {
  187.     register int n;
  188.         char *p;
  189.  
  190.         if ((p = malloc (n = strlen(s)+1)) != NULL)
  191.                 (void) memcpy(p, s, n);
  192.         return (p);
  193. }
  194.  
  195. #define USAGE "Usage: M4 [-D name[=val]] [-U name] [ -o ofile ] file ...\n"
  196.  
  197. void usage (void)
  198. {
  199.         fprintf(stderr, USAGE);
  200.         exit(1);
  201. }
  202.  
  203. /*
  204.  * killdiv - get rid of the diversion files
  205.  *
  206.  */
  207. static void killdiv (void)
  208. {
  209.         register int n;
  210.  
  211.         for (n = 0; n < MAXOUT; n++)
  212.         {
  213.             if (outfile[n].ptr)
  214.             {
  215.                     if (outfile[n].fp != NULL)
  216.                             (void) fclose (outfile[n].fp);
  217.                             
  218.             (void) remove (outfile[n].name);
  219.             outfile[n].ptr = 0L;
  220.                 }
  221.         }
  222. }
  223.  
  224. #ifdef GETOPT
  225. /*
  226.  * H. Spencer getopt - get option letter from argv
  227.  * 
  228.  *
  229. #include <stdio.h>
  230.  *
  231.  */
  232.  
  233. char    *optarg;    /* Global argument pointer. */
  234. int    optind = 0;    /* Global argv index. */
  235.  
  236. static char    *scan = NULL;    /* Private scan pointer. */
  237.  
  238. extern char    *index();
  239.  
  240. int getopt (int argc, char *argv[], char *optstring)
  241. {
  242.     register char c;
  243.     register char *place;
  244.  
  245.     optarg = NULL;
  246.  
  247.     if (scan == NULL || *scan == '\0') {
  248.         if (optind == 0)
  249.             optind++;
  250.     
  251.         if (optind >= argc || argv[optind][0] != '-' || argv[optind][1] == '\0')
  252.             return(EOF);
  253.         if (strcmp(argv[optind], "--")==0) {
  254.             optind++;
  255.             return(EOF);
  256.         }
  257.     
  258.         scan = argv[optind]+1;
  259.         optind++;
  260.     }
  261.  
  262.     c = *scan++;
  263.     place = index(optstring, c);
  264.  
  265.     if (place == NULL || c == ':') {
  266.         fprintf(stderr, "%s: unknown option -%c\n", argv[0], c);
  267.         return('?');
  268.     }
  269.  
  270.     place++;
  271.     if (*place == ':') {
  272.         if (*scan != '\0') {
  273.             optarg = scan;
  274.             scan = NULL;
  275.         } else {
  276.             optarg = argv[optind];
  277.             optind++;
  278.         }
  279.     }
  280.  
  281.     return(c);
  282. }
  283.    
  284. #endif
  285.  
  286. #ifdef DUFFCP
  287. /*
  288.  * This code uses Duff's Device (tm Tom Duff)
  289.  * to unroll the copying loop:
  290.  * while (count-- > 0)
  291.  *    *to++ = *from++;
  292.  */
  293.  
  294. #define COPYBYTE     *to++ = *from++
  295.  
  296. void memcpy (char *to, char *from, int count)
  297. {
  298.     if (count > 0) {
  299.         register int loops = (count+8-1) >> 3;    /* div 8 round up */
  300.  
  301.         switch (count&(8-1)) {            /* mod 8 */
  302.         case 0: do {
  303.             COPYBYTE;
  304.         case 7:    COPYBYTE;
  305.         case 6:    COPYBYTE;
  306.         case 5:    COPYBYTE;
  307.         case 4:    COPYBYTE;
  308.         case 3:    COPYBYTE;
  309.         case 2:    COPYBYTE;
  310.         case 1:    COPYBYTE;
  311.             } while (--loops > 0);
  312.         }
  313.  
  314.     }
  315. }
  316.  
  317. #endif
  318.